package net.vinote.smart.platform.service.dw.handler;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import net.vinote.smart.platform.comm.DateFunction;
import net.vinote.smart.platform.comm.PlatformConst;
import net.vinote.smart.platform.comm.StringFunction;
import net.vinote.smart.platform.module.database.DBManager;
import net.vinote.smart.platform.module.database.DBManagerFactory;
import net.vinote.smart.platform.module.database.DBTransaction;
import net.vinote.smart.platform.module.database.Field;
import net.vinote.smart.platform.module.database.PrimaryKeyGenerateStrategy;
import net.vinote.smart.platform.module.database.SerialNoManager;
import net.vinote.smart.platform.module.database.Table;
import net.vinote.smart.platform.module.database.bo.BizObject;
import net.vinote.smart.platform.service.DWException;
import net.vinote.smart.platform.service.SRE;
import net.vinote.smart.platform.service.bean.DataWindowCatalog;
import net.vinote.smart.platform.service.bean.DataWindowLibrary;
import net.vinote.smart.platform.service.bean.User;
import net.vinote.smart.platform.service.dw.html.css.CSS;
import net.vinote.smart.platform.service.util.Permission;
import net.vinote.smart.platform.service.util.Permission.PermissionEnum;
import net.vinote.smart.platform.service.util.Permission.PermissionRelation;

@HandlerPerimissionAnnotation(
		insert = @Permission(
				PermissionRelation = PermissionRelation.NOT,
				value = { PermissionEnum.SMART_DISABLE }),
		update = @Permission(
				PermissionRelation = PermissionRelation.NOT,
				value = { PermissionEnum.SMART_DISABLE }),
		delete = @Permission(
				PermissionRelation = PermissionRelation.NOT,
				value = { PermissionEnum.SMART_DISABLE }), query = @Permission(
				PermissionRelation = PermissionRelation.NOT,
				value = { PermissionEnum.SMART_DISABLE }))
public class CommonHandler {
	protected HttpServletRequest request;

	private boolean isInsert; // 是否为新增状态

	protected String error = "";// 错误信息

	private String doNo;

	private Map<String, String> defaultValue = new HashMap<String, String>();// 各属性的默认值

	private Map<String, Map<CSS, String>> fieldsCssAttributesMap = new HashMap<String, Map<CSS, String>>();

	// 存储HtmlTemplate属性需要进行修改字段名与各属性值
	private Map<String, Map<String, Object>> htmlTagFieldMap = new HashMap<String, Map<String, Object>>();

	/**
	 * 指定失效的字段,以逗号分隔各字段<br/>
	 * 例:"field1,field2"
	 * 
	 * @param fields
	 */
	public final void setReadOnly(String fields, boolean isReadOnly) {
		if (fields != null) {
			String[] fieldArray = fields.split(",");
			for (String field : fieldArray) {
				field = field.toUpperCase();
				Map<CSS, String> fieldCssMap = fieldsCssAttributesMap
						.get(field);
				if (isReadOnly) {// 设置字段的只读属性
					if (fieldCssMap == null) {
						fieldCssMap = new HashMap<CSS, String>();
						fieldsCssAttributesMap.put(field, fieldCssMap);
					}
					fieldCssMap.put(CSS.READONLY, CSS.CSS_READONLY);
				} else {
					if (fieldCssMap != null) {
						fieldCssMap.remove(CSS.READONLY);// 移除字段的只读属性
					}
				}
			}
		}
	}

	public final void setDisabledCSSFields(String fields, boolean isDisabled) {
		if (fields != null) {
			String[] fieldArray = fields.split(",");
			for (String field : fieldArray) {
				field = field.toUpperCase();
				Map<CSS, String> fieldCssMap = fieldsCssAttributesMap
						.get(field);
				if (isDisabled) {// 设置字段的只读属性
					if (fieldCssMap == null) {
						fieldCssMap = new HashMap<CSS, String>();
						fieldsCssAttributesMap.put(field, fieldCssMap);
					}
					fieldCssMap.put(CSS.DISABLED, CSS.CSS_DISABLED);
				} else {
					if (fieldCssMap != null) {
						fieldCssMap.remove(CSS.DISABLED);// 移除字段的只读属性
					}
				}
			}
		}
	}

	/**
	 * 获取所配字段的属性集
	 * 
	 * @return
	 */
	public final Map<String, Map<CSS, String>> getFieldsCssAttributes() {
		return fieldsCssAttributesMap;
	}

	/**
	 * 为指定的字段设置样式
	 * 
	 * @param fields
	 *            字段 ，以逗号分隔
	 * @param css
	 *            样式
	 * @param value
	 *            样式值
	 */
	public final void setCssAttribute(String fields, CSS css, String value) {
		if (fields != null) {
			String[] fieldArray = fields.split(",");
			for (String field : fieldArray) {
				field = field.toUpperCase();
				// 获取该字段的属性集
				Map<CSS, String> attrMap = fieldsCssAttributesMap.get(field);
				if (attrMap == null) {
					attrMap = new HashMap<CSS, String>();
					fieldsCssAttributesMap.put(field, attrMap);
				}
				attrMap.put(css, value);
			}
		}

	}

	/**
	 * 更新字段的HtmlTag属性
	 **/
	public final void updateHtmlTag(String fields, String attr, Object value) {
		fields = fields.toUpperCase();
		String[] fieldArray = fields.split(",");
		for (String field : fieldArray) {
			Map<String, Object> fieldAtttMap = htmlTagFieldMap.get(field);
			if (fieldAtttMap == null) {
				fieldAtttMap = new HashMap<String, Object>();
				htmlTagFieldMap.put(field, fieldAtttMap);
			}
			fieldAtttMap.put(attr, value);
		}
	}

	public final Map<String, Map<String, Object>> getHtmlTagFieldMap() {
		return htmlTagFieldMap;
	}

	public final Map<String, String> getDefaultValue() {
		return defaultValue;
	}

	public final void setDefaultValue(String key, String defaultValue) {
		this.defaultValue.put(key, defaultValue);
	}

	public final void doSave(DBTransaction tx, BizObject bo, String dwNo)
			throws SQLException {
		DataWindowCatalog dwCatalog = SRE.getDataWindowCatalog(dwNo);
		String tableName = dwCatalog.getMainTable();// 主表名称
		Table mainTable = SRE.getAttribute(PlatformConst.SRE_PREFIX_TABLE
				+ tableName, Table.class);
		List<Field> key = mainTable.getKey();
		if (key == null || key.size() == 0) {
			throw new DWException("表" + tableName + "未指定主键,无法对其进行数据维护!");
		}
		for (Field keyFiled : key) {
			String keyVal = bo.getAttribute(keyFiled.getFieldName());
			if (keyVal == null) {
				throw new DWException("主键缺失,无法对其进行数据维护!");
			}
		}

		// 校验数据的是否满足基本条件
		if (!basicCheck(bo) || !validityCheck(bo, isInsert)) {
			throw new DWException(this.error);
		}

		List<Field> mainField = getMainTableFields(dwNo);
		User curUser = (User) (request.getSession().getAttribute("user"));
		if (curUser != null) {
			bo.setAttribute(isInsert ? "INPUTUSERID" : "UPDATEUSERID",
					curUser.getUserID());
		}
		bo.setAttribute(isInsert ? "INPUTDATE" : "UPDATEDATE",
				DateFunction.getCurrentTime());
		if (isInsert) {
			beforeInsert(bo, tx);
			doInsert(bo, mainField, tx);
			afterInsert(bo, tx);
		} else {
			beforeUpdate(bo, tx);
			doUpdate(bo, mainField, tx);
			afterUpdate(bo, tx);
		}
	}

	/**
	 * 获取显示模板中的主表字段
	 * 
	 * @param mainTable
	 * @param dwNo
	 * @return
	 */
	private List<Field> getMainTableFields(String doNo) {
		List<DataWindowLibrary> list = SRE.getDataWindowLibrary(doNo);
		String tableName = SRE.getDataWindowCatalog(doNo).getMainTable();
		Table table = SRE.getTable(tableName);
		List<Field> fieldList = new ArrayList<Field>();
		for (Field f : table.getFields()) {
			for (DataWindowLibrary bo : list) {
				String dataObj = bo.getDataObj();
				if ((dataObj == null || "".equals(dataObj.trim())
						|| tableName.equalsIgnoreCase(dataObj) || dataObj
							.equalsIgnoreCase("O"))
						&& f.getFieldName().equalsIgnoreCase(bo.getFieldCode())) {
					fieldList.add(f);
				}
			}
		}
		return fieldList;
	}

	private void doInsert(BizObject bo, List<Field> fields, DBTransaction tx)
			throws SQLException {
		if (fields == null || fields.size() == 0) {
			throw new DWException("没有要保存字段!");
		}
		String tableName = fields.get(0).getTableName();
		Table mainTable = SRE.getAttribute(PlatformConst.SRE_PREFIX_TABLE
				+ tableName, Table.class);
		List<Field> keys = mainTable.getKey();// 获取该表的主键字段
		BizObject subBo = new BizObject();
		for (Field filed : fields) {
			subBo.setAttribute(filed.getFieldName(),
					bo.getAttribute(filed.getFieldName()));
		}
		for (Field key : keys) {
			if (bo.getAttribute(key.getFieldName()) == null
					|| "".equals(bo.getAttribute(key.getFieldName()).trim())) {
				// 暂不支持
				/*
				 * String keyStrategy = SRE.getDataWindowCatalog(doNo)
				 * .getKeyStrategy(); try { Object ojb =
				 * Class.forName(keyStrategy).newInstance(); if (ojb instanceof
				 * PrimaryKeyGenerateStrategy) {
				 * SerialNoManager.getInstance().getSeialNo(
				 * (PrimaryKeyGenerateStrategy) ojb); } else {
				 * 
				 * } } catch (Exception e) {
				 * RunLogger.getLogger().log(Level.WARNING, keyStrategy +
				 * " is exception"); e.printStackTrace(); }
				 */
				String strategyClazz = SRE.getDataWindowCatalog(doNo)
						.getKeyStrategy();
				String serialNo;
				if (StringFunction.nullToBlank(strategyClazz).length() == 0) {
					serialNo = SerialNoManager.getInstance().getSerialNo(
							tableName);
				} else {
					PrimaryKeyGenerateStrategy strategy = SerialNoManager
							.getInstance().getStrategy(strategyClazz);
					strategy.setTableName(tableName);
					strategy.setBizObject(bo);
					serialNo = strategy.getSerialNo();
				}
				bo.setAttribute(key.getFieldName(), serialNo);
				subBo.setAttribute(key.getFieldName(),
						bo.getAttribute(key.getFieldName()));
			}
		}
		DBManager bm = DBManagerFactory.getInstance(tableName);
		tx.join(bm);
		bm.saveBizObject(subBo);
	}

	/**
	 * @param bo
	 * @param fields
	 * @param tx
	 * @throws SQLException
	 */
	private void doUpdate(BizObject bo, List<Field> fields, DBTransaction tx)
			throws SQLException {
		if (fields == null || fields.size() == 0) {
			throw new DWException("没有要更新的字段!");
		}
		String tableName = fields.get(0).getTableName();
		BizObject subBo = new BizObject();
		for (Field filed : fields) {
			if (bo.containsKey(filed.getFieldName())) {
				subBo.setAttribute(filed.getFieldName(),
						bo.getAttribute(filed.getFieldName()));
			}
		}
		DBManager bm = DBManagerFactory.getInstance(tableName);
		tx.join(bm);
		bm.updateBizObject(subBo);
	}

	public final void doDelete(BizObject bo, DBTransaction tx)
			throws SQLException {
		beforeDelete(bo, tx);
		Table table = SRE.getTable(SRE.getDataWindowCatalog(doNo)
				.getMainTable());
		List<Field> keyList = table.getKey();
		int size = keyList.size();
		String[] keyNames = new String[size];
		String[] keyValues = new String[size];
		for (int i = 0; i < size; i++) {
			keyNames[i] = keyList.get(i).getFieldName();
			keyValues[i] = bo.getAttribute(keyNames[i]);
		}
		DBManager bm = new DBManager(table.getTableName());
		tx.join(bm);
		bm.delete(keyNames, keyValues);
		afterDelete(bo, tx);
	}

	public void initDisplayForEdit(BizObject bo) {

	}

	public void initDisplayForAdd(BizObject bo) {
	}

	private boolean basicCheck(BizObject bo) {

		List<DataWindowLibrary> libList = SRE.getDataWindowLibrary(doNo);
		for (DataWindowLibrary lib : libList) {
			String fieldCode = lib.getFieldCode();
			String regex = lib.getRegex();
			String attrVal = bo.getAttribute(fieldCode);
			if (StringFunction.nullToBlank(regex).length() > 0
					&& !attrVal.matches(regex)) {
				String validMsg = StringFunction.nullToBlank(lib
						.getInvalidMessage());
				if (validMsg.length() > 0) {
					this.error += "字段: " + lib.getFieldName() + " 非法:"
							+ validMsg + " ;";
				} else {
					this.error += "字段: " + lib.getFieldName() + " 不符合正则:"
							+ regex + " ;";
				}
			}
		}
		return StringFunction.nullToBlank(this.error).length() == 0;
	}

	/**
	 * 对传入对象进行校验
	 * 
	 * @param bo
	 * @param isInsert
	 * @return
	 */
	protected boolean validityCheck(BizObject bo, boolean isInsert) {
		return true;
	}

	protected void beforeInsert(BizObject bo, DBTransaction tx) {
	}

	protected void afterInsert(BizObject bo, DBTransaction tx) {
	}

	protected void beforeUpdate(BizObject bo, DBTransaction tx) {
	}

	protected void afterUpdate(BizObject bo, DBTransaction tx) {
	}

	protected void beforeDelete(BizObject bo, DBTransaction tx)
			throws SQLException {
	}

	protected void afterDelete(BizObject bo, DBTransaction tx)
			throws SQLException {
	}

	public final void setRequest(HttpServletRequest request) {
		this.request = request;
	}

	public final boolean isInsert() {
		return isInsert;
	}

	public final void setInsert(boolean isInsert) {
		this.isInsert = isInsert;
	}

	public final String getDoNo() {
		return doNo;
	}

	public final void setDoNo(String doNo) {
		this.doNo = doNo;
	}

}
